home *** CD-ROM | disk | FTP | other *** search
-
- title scavenge Copyright (c) T. Jennings 1983
- ;
- ;****************************************
- ;* *
- ;* SCAVENGE *
- ;* *
- ;* Mark bad blocks on MSDOS *
- ;* as allocated in the FAT. *
- ;* *
- ;* T. Jennings 5 June 82 *
- ;* created 15 Sept. 82 *
- ;* Modified 14 December 1984 *
- ;* by David Gwillim *
- ;* *
- ;* *
- ;****************************************
- ;
- ;***********************************************************************
- ;** **
- ;** SCAV2XX was modified by David Gwillim to dynamically allocate **
- ;** memory to the variables BLKBUF and FATBUF when the program **
- ;** is started - this drastically reduced the size of the .COM file **
- ;** from 17K on disk to just over 1K, while still allowing the **
- ;** checking of disks with block sizes up to 16K Bytes. Also **
- ;** changed was the access to disk to determine its statistics **
- ;** (Number of Blocks, Blocksize etc) this is now done AFTER the **
- ;** pause command when the program is first started, permitting **
- ;** the program to be run with a single floppy drive. Code was **
- ;** also added to display the block size of the disk in bytes **
- ;** as part of the statistics, plus some alert tones for various **
- ;** parts of the program. **
- ;** **
- ;** I also added a more graceful exit than via ^C or Cntrl-Break **
- ;** as this would often leave you on the wrong drive if you aborted **
- ;** mid way through the block check and also would not give you the **
- ;** chance to update the FAT with any bad blocks found so far. **
- ;** **
- ;** A logical improvement to the program would be to add to the **
- ;** code so the program could report the names of the files which **
- ;** contain any bad blocks found, so the user could handle those **
- ;** files, or at least be aware that the data in them was corrupted. **
- ;** **
- ;** This is a very useful program and can give you great peace of **
- ;** mind if you own a hard disk and want to be sure that all is OK. **
- ;** If anyone takes a crack at doing the improvements I mentioned **
- ;** or finds and fixes any bugs, I would be delighted to hear of **
- ;** them. **
- ;** **
- ;** David Gwillim **
- ;** 1414 N. Catalina Street **
- ;** Los Angeles CA 90027 **
- ;** **
- ;************************************************************************
- ;
- ;Reads all sectors in logical MSDOS blocks
- ;and marks the file allocation tables such
- ;that the blocks are permanently allocated
- ;where CHKDSK will not deallocate them.
- ;
- ;
- ;This version works on any 2.xx MSDOS or
- ;PCDOS, on any media type, fixed or removable.
- ;One (major) limitation: it will not map out
- ;blocks that are already allocated to a file;
- ;it will say "block used", but won't tell you
- ;which file it is in.
- ;
- ;If SCAVENGE finds any bad blocks, it will ask
- ;you whether or not you want the disk updated.
- ;You can safely run it just to see if the disk
- ;is OK.
- ;
- ;MASM, LINK, then EXE2BIN this to make a COM
- ;file. It will not run as an EXE file. NOTE:
- ;LINK will give you a 'Warning: no STACK
- ;segment' error: ignore it.
- ;
- cr equ 0dh
- lf equ 0ah
-
- ;Beep procedure count values
- ;---------------------------
- ;To generate a given freqency note out of the speaker with the Beep procedure
- ;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
- ;must be loaded with a value such that the 8253 input clock frequency
- ;(1.19318 MHz) divided by the count figure equals the audio frequency.
-
- f176Hz equ 6779 ; 176 Hz count value
- f352Hz equ 3390 ; 352 Hz count value
- f704Hz equ 1695 ; 704 Hz count value
- f1408Hz equ 847 ; 1408 Hz count value
-
- page
- cgroup group code
- code segment byte public 'code'
- assume cs:cgroup,ds:cgroup,ss:cgroup
- ;
- ;MSDOS page 0 stuff.
- ;
- org 5ch
- tfcb label byte
-
- org 80h
- tbuff label byte
-
- org 100h
- scavenge:
- jmp start
- ;
- ;Disk parameters:
- ;
- blkcnt dw (?) ;blocks this disk
- blksize dw (?) ;sectors per block
- secsize dw (?) ;phys. sector size
- badcnt dw (?) ;# bad blocks found
- newbad dw (?) ;new bad ones
- block dw (?) ;current block
- sector dw (?) ;sector to read
- disk db (?) ;selected disk
- curdsk db (?) ;current disk.
- fatsec dw (?) ;1st FAT sector,
- fatcnt dw (?) ;FAT sec count.
-
- dw 128 dup (?)
- stack dw (?) ;what else
- page
- ;
- ;Say who we are, describe the disk we are
- ;about to fix, ask to continue or abort.
- ;
- start: mov ax,cs
- mov ds,ax
- cli ;Disable interrupts while we move stack
- mov ss,ax
- mov sp,offset stack
- sti ;Re-enable interrupts
- mov dx,offset signon
- call putstr
-
- mov bx,f176Hz ;Alert user audibly
- call beep
- mov bx,f704Hz
- call beep
- mov bx,f352Hz
- call beep
- mov bx,f1408Hz
- call beep
-
- call ina
- or al,20h ;Make character lower case
- cmp al,'q' ;Quit?
- jne st0
- mov dx,offset abort
- call putstr
- int 20h
-
- st0: call setup ;get disk stuff
- jnc st1
-
- call putstr
- int 20h ;error.
-
- st1: call liststat ;describe dsk
- ;
- ;Find all the bad blocks, if any, display them,
- ;ask if we should update the FAT. If so, write
- ;it out.
- ;
- mov dx,offset crlf
- call putstr
- call findbad ;map bad,
- call listbad ;list them,
- cmp newbad,0 ;if new bad
- je st2 ;blocks...
-
- mov dx,offset updstr ;ask if we
- call putstr ;should update
- call ina
- and al,5fh
- cmp al,'Y'
- jne st1A
- mov al,disk ;write out the
- mov dx,fatsec ;FAT,
- mov cx,fatcnt
- mov bx,offset fatbuf
- int 26h
- pop ax ;pop flags
- mov dx,offset update
- call putstr
- jmp st2
- st1A: mov dx,offset noupdte
- call putstr
- st2: mov al,curdsk ;reselect the
- call seldsk ;original disk
- int 20h
-
- signon db cr,lf,9,'*********************************************'
- db cr,lf,9,'* DOS 2.xx Bad Sector Mapper - Version 3.00 *'
- db cr,lf,9,'* Updated by David Gwillim 18 December 1984 *'
- db cr,lf,9,'* Original program by T. Jennings 5 June 83 *'
- db cr,lf,9,'*********************************************'
- db cr,lf,lf
- db 'Type Q to abort at any time, any other key to continue ...'
- db cr,lf,'$'
- updstr db cr,lf,lf,'Want the disk updated? [y,n] $'
- noupdte db cr,lf,lf,'FAT not updated',cr,lf,'$'
- update db cr,lf,lf,'FAT updated',cr,lf,'$'
- crlf db cr,lf,'$'
- page
- ;
- ;Get the data on the specified disk. Return
- ;carry if no drive specified. Returns ES:DI
- ;pointing to the FAT for the selected drive.
- ;
- setup: call initdsk ;reset dsk sys,
- call getdsk ;get current,
- mov curdsk,al ;save it,
- mov al,tfcb ;make sure a
- cmp al,0 ;new one spec'd
- stc ;quit if none,
- mov dx,offset strstr
- jz gd1
- dec al ;make 0-N,
- mov disk,al
- call seldsk ;select,
-
- push ds ;save local DS,
- mov ah,1bh
- int 21h
- pop ds
- mov blkcnt,dx ;save # blocks,
- mov secsize,cx ;sector size,
- mov ah,0
- mov blksize,ax ;secs/block.
-
- push ds ;now get the
- mov dl,disk
- inc dl ;drive 1=A, b=2
- mov ah,32h ;FAT,
- int 21h ;get the DPB,
-
- mov cx,[bx+15] ;CX= sec count,
- mov ch,0
- mov dx,[bx+6] ;DX= 1st sec,
- pop ds
- mov fatcnt,cx ;save both,
- mov fatsec,dx
-
- mov al,disk ;AL= drive #,
- mov bx,offset fatbuf ;DS:BX= buffer
- int 25h ;read the FAT,
- pop ax ;pop flags
- mov dx,offset bscstr
- gd1: ret
- strstr db cr,lf,'Must specify a disk drive.$'
- bscstr db cr,lf,'Bad FAT sector: disk not useable.$'
-
- page
- ;
- ;Read the entire disk looking for bad blocks.
- ;When one is found, go mark it as an allocated
- ;bad block.
- ;
- findbad:
- mov block,0 ;1st block,
- mov badcnt,0 ;none yet,
-
- fb1: call kbdchk ;QUIT character input from the keyboard?
- jnc fb1A
- mov dx,offset abort
- call putstr
- ret
-
- fb1A: mov dx,offset blkstr ;type 'block '
- call putstr
- mov bx,block ;block number,
- call outdec
- call readblk ;read a block,
- jnc fb3 ;if bad,
- inc badcnt ;count it,
- mov dx,offset badstr
- call putstr ;type 'bad'
- call mapout ;mark bad,
- mov dx,offset cntstr ;error if cant
- jc fb2
- add newbad,cx ;count it,
- mov dx,offset alrstr
- jcxz fb2 ;already marked
- mov dx,offset mrkstr
-
- mov bx,f704Hz ;Warn user audibly
- call beep
- mov bx,f176Hz
- call beep
-
- fb2: call putstr
-
- mov bx,f1408Hz ;Warn user audibly
- call beep
- mov bx,f176Hz
- call beep
-
- fb3: inc block ;next block,
- dec blkcnt ;another...
- jnz fb1 ;keep looking.
- ret
-
-
- blkstr db cr,'Block $'
- badstr db ' bad,$'
- alrstr db ' already marked.',cr,lf,'$'
- mrkstr db ' mapped out.',lf,'$'
- cntstr db ' already used! I dont know which file.',lf,'$'
- abort db ' ... Aborting program',cr,lf,lf,'$'
-
- page
- ;
- ;Mark the current block as bad in the FAT.
- ;Multiply the block number by 1.5 to find the
- ;block number, (actually *3, /2) and if not
- ;used, mark it bad. If used, report which file
- ;it's in. If it's already mapped as bad,
- ;return CX=0, else return CX=1.
- ;
- mapout:
- mov bx,block ;block,
- shl bx,1 ;first times 2,
- add bx,block ;then add one to make times 3,
- shr bx,1 ;now divide by 2,
- mov ax,word ptr fatbuf[bx] ;get word,
- ;
- ;If carry is set, we want the high 12 bits in
- ;the word in AX, else the low 12 bits. Set CH
- ;as the shift count, DX as the mask.
- ;
- mov ch,0 ;assume low,
- mov dx,0fffh
- jnc mo1
- mov ch,4 ;else high 12,
- mov dx,0fff0h
- mo1: and ax,dx ;mask it,
- mov cl,ch
- shr ax,cl ;shift it,
- ;
- ;AX is the block number; if it's anything
- ;but 000 or ff7, return with carry set,
- ;indicating that it's already used.
- ;
- cmp ax,0ff7h ;if ff7,
- je mo2 ;already marked
- cmp ax,0 ;if allocated,
- je mo3
- stc ;error!
- mo2: mov cx,0 ;none mapped,
- ret
- ;
- ;Bad unused block. Mark as bad in the FAT.
- ;
- mo3: mov ax,0ff7h ;marker,
- mov cl,ch
- shl ax,cl ;shift it,
- or word ptr fatbuf[bx],ax ;mark it.
- mov cx,1 ;1 mapped,
- ret
- page
- ;
- ;Read one block, return carry set if read
- ;error. Leave the useless data in the buffer
- ;following the end of this program.
- ;
- readblk:
- mov ax,block ;find start
- mov cx,blksize ;sector,
- mul cx ;CX= count,
- mov dx,ax ;DX= sector,
- mov al,disk
- mov bx,offset blkbuf ;our buffer,
- int 25h ;read sectors,
- pop dx ;pop flags,
- ret
- page
- ;
- ;List the general info on the disk, like
- ;number of blocks, block size, FAT size & location, etc.
- ;
- liststat:
- mov dx,offset st1str
- call putstr
- mov al,disk
- add al,'A'
- call outa
- mov dx,offset st2str
- call putstr
- mov bx,blkcnt
- call outdec
- mov dx,offset st3str
- call putstr
- mov ax,512
- mul blksize
- mov bx,ax
- call outdec
- mov dx,offset st4str
- call putstr
- mov bx,fatcnt
- call outdec
- mov dx,offset st5str
- call putstr
- mov bx,fatsec
- call outdec
- mov dx,offset st6str
- call putstr
- ret
-
- ;Disk A: Total of 12345 data blocks 1024 bytes each.
-
- st1str db cr,lf,'Disk $'
- st2str db ': Total of $'
- st3str db ' data blocks $'
- st4str db ' bytes each.',cr,lf,'$'
- st5str db ' FAT sectors, first FAT sector is logical sector $'
- st6str db cr,lf,'$'
- ;
- ;List out the bad things about this disk.
- ;
- listbad:
- mov dx,offset bd1str
- call putstr
- mov bx,badcnt
- call outdec
- mov dx,offset bd2str
- call putstr
- mov bx,newbad
- call outdec
- mov dx,offset bd3str
- call putstr
- ret
-
- ;Total of 12345 bad blocks, found 12234 more this pass.
- bd1str db cr,'Total of $' ;note no linefeed.
- bd2str db ' bad blocks, found $'
- bd3str db ' more this pass.',cr,lf,'$'
- page
- ;
- ;Generally useful system calls.
- ;
- putstr: mov ah,9
- int 21h
- ret
- ;
- ;Type BX in decimal, suppressing leading
- ;zeros.
- ;
- outdec: mov cl,0 ;0 suppress flag,
- mov dx,10000
- call rsdiv
- mov dx,1000
- call rsdiv
- mov dx,100
- call rsdiv
- mov dx,10
- call rsdiv
- mov ch,bl
- jmp odf
-
- rsdiv: mov ch,-1 ;iteration -1,
- rs1: inc ch ;count,
- sub bx,dx ;subtract,
- jnc rs1 ;til underflow,
- add bx,dx ;adjust back,
- cmp ch,0 ;if non-zero,
- jne odf ;type it,
- test cl,1 ;dont type 0's
- jnz odf ;if leading,
- ret
-
- odf: push dx
- mov dl,ch
- add dl,'0' ;ASCII,
- mov ah,2
- int 21h
- pop dx
- mov cl,1 ;no suppress,
- ret
- page
- ;
- ;More system calls.
- ;
- seldsk: mov dl,al ;select disk,
- mov ah,0eh
- int 21h
- ret
-
- getdsk: mov ah,19h
- int 21h
- ret
-
- initdsk:mov ah,0dh
- int 21h
- ret
-
- ina: mov ah,0ch ;char in with no echo
- mov al,8 ;and flush.
- int 21h
- ret
-
- kbdchk: mov ah,0Bh ;Check keyboard for character waiting
- int 21h
- cmp al,0
- jz chk1
- mov ah,8 ;Character waiting - see what it is
- int 21h
- or al,20h ;Make it lower case
- cmp al,'q' ;Time to QUIT?
- je chk2 ;Yes
- chk1: clc ;No - Make sure carry flag is cleared
- ret
- chk2: stc ;Yep - set carry flag
- ret
-
- outa: mov dl,al
- mov ah,2
- int 21h
- ret
-
- ;
- ; BEEP - entry conditions BX register contains count figure for frequency
- ; to be generated.
- ;
- beep: mov al,0b6h ; Channel 2, LSB then MSB, Square Wave, Binary
- out 43h,al ; Program 8253 command register
- mov ax,bx ; Get the frequency to be generated
- out 42h,al ; Load Channel 2 count register LSB
- mov al,ah
- out 42h,al ; Load Channel 2 count register MSB
- in al,61h ; Read settings from 8255 PPI I/O Port "PB"
- mov ah,al ; Save original settings in AH
- or al,3 ; Enable Timer Channel 2 & Speaker data
- out 61h,al ; program the 8255 with new setting-speaker on
- sub cx,cx ; Sneaky way to put 0FFFFH into CX when
- wait2: loop wait2 ; LOOP is first executed
- mov al,ah ; Get original 8255 Port "PB" settings
- out 61h,al ; Reset port to original values-speaker off
- ret
-
- blkbuf equ $ ;cluster buffer
-
- fatbuf equ $+16384 ;FAT buffer.
-
- code ends
-
- end scavenge